package com.kokomi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kokomi.handler.Assert;
import com.kokomi.mapper.AddressMapper;
import com.kokomi.mapper.ItemMapper;
import com.kokomi.pojo.*;
import com.kokomi.pojo.VO.CartItemVo;
import com.kokomi.pojo.VO.CartVo;
import com.kokomi.pojo.VO.OrderItemVo;
import com.kokomi.pojo.VO.OrderVo;
import com.kokomi.pojo.enumeration.BusinessCode;
import com.kokomi.pojo.enumeration.OrderStatus;
import com.kokomi.service.BookService;
import com.kokomi.service.CartService;
import com.kokomi.service.OrderService;
import com.kokomi.mapper.OrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author klioe
* @description 针对表【t_order】的数据库操作Service实现
* @createDate 2025-04-10 14:44:12
*/
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
    implements OrderService{

    @Autowired
    private OrderMapper orderMapper;  //订单数据层

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;   //消息队列

    @Autowired
    private CartService cartService;   //购物车业务层

    @Autowired
    private ItemMapper itemMapper;   //订单项
    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private BookService bookService;


    /**
     * 查询某个用户：指定状态的订单，如果没有指定状态，则查询所有的订单
     *
     * @param userId 用户id
     * @param status 订单状态
     */
    @Override
    @Transactional //开启事务，因为有多个插入操作
    public List<OrderVo> queryOrder(Long userId, Integer status) {
        //查询order表
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        //查询某个用户的订单
        wrapper.eq(Order::getUserId, userId);
        //如果不为0，则查询指定状态的订单
        if(status!=0){
            wrapper.eq(Order::getState, status);
        }
        //按下单时间倒序排列
        wrapper.orderByDesc(Order::getCreateTime);
        List<Order> orders = orderMapper.selectList(wrapper);

        //将订单对象，转换为订单视图对象
        List<OrderVo> orderVos = orders.stream().map(order -> {
            //复制订单对象的属性到OrderVo对象中
            OrderVo orderVo = BeanUtil.copyProperties(order, OrderVo.class);
            //单独设置属性
            orderVo.setOrderStatus(order.getState().toString());
            //订单状态文字描述
            orderVo.setOrderStatus(OrderStatus.matchCode(order.getState()).getDescribe());

            // 查询address  查询地址对象
            Address address = addressMapper.selectById(order.getAddressId());
            orderVo.setAddress(address.getProvince());
            orderVo.setPhone(address.getTelephone());

            // 拼接详细地址
            orderVo.setAddress(address.getProvince()+address.getCity()+address.getArea()+address.getDetailAddress());
            orderVo.setUserId(String.valueOf(userId));

            // 订单明细
            LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();

            // 查询订单项
            queryWrapper.eq(Item::getOrderId, order.getId());
            List<Item> items = itemMapper.selectList(queryWrapper);

            // 订单明细转成订单项视图对象
            List<OrderItemVo> orderItemVos = items.stream().map(item -> {
                // 复制订单项对象的属性到OrderItemVo对象中
                OrderItemVo orderItemVo = BeanUtil.copyProperties(item, OrderItemVo.class);

                // 根据书籍id查询图书，获取图片地址()
                Book byId = bookService.getById(item.getBookId());
                orderItemVo.setBookImg(byId.getImgSrc());
                return orderItemVo;
            }).collect(Collectors.toList());
            // 添加到订单的属性中
            orderVo.setOrderItem(orderItemVos);
            return orderVo;
        }).collect(Collectors.toList());
        return orderVos;
    }

    @Override
    @Transactional //开启事务，因为有多个插入操作
    public String createOrder(Long userId, Long addressId) {
        //1、生成订单对象（生产订单编号）
        long orderId = IdUtil.getSnowflake(1,1).nextId();
        //2、获取用户的购物车对象
        CartVo cartVo = (CartVo) redisTemplate.opsForValue().get(RedisConst.USER_CART_PREFIX + ":" + userId);
        //3、遍历购物车判断每本书的库存是否充足
        HashOperations ops = redisTemplate.opsForHash();

        for(CartItemVo cartItemVo : cartVo.getItemList()){
            // 获取库存数量
            Integer storeCount = (Integer)ops.get(RedisConst.BOOK_STORAGE, cartItemVo.getBookId().toString());
            // 库纯数量小于购买量，返回提示消息
            Assert.error(storeCount<cartItemVo.getQuantity(), BusinessCode.STORAGE_NOT_ENOUGH);
            // 库存充足，则减少库存
            ops.increment(RedisConst.BOOK_STORAGE, cartItemVo.getBookId().toString(), -cartItemVo.getQuantity());

            //每个购物车项是一个订单项
            //4、生成订单项
            Item item = new Item();
            item.setBookId(cartItemVo.getBookId());
            item.setBookName(cartItemVo.getName());
            item.setPrice(BigDecimal.valueOf(cartItemVo.getPrice()));
            item.setBuyCount(cartItemVo.getQuantity());
            item.setSumPrice(BigDecimal.valueOf(cartItemVo.getSum()));
            item.setOrderId(orderId);
            item.setState(OrderStatus.NO_PAY.getCode());

            itemMapper.insert(item);
        }
        // 5、生成订单
        Order order = new Order();
        order.setId(orderId); // 主键
        String Number ="WNXY_BOOK"+orderId;
        order.setOrderNum(Number);
        order.setTotalPrice(BigDecimal.valueOf(cartVo.getTotalPrice()));
        order.setUserId(userId);
        order.setAddressId(new Integer(addressId+""));
        order.setState(OrderStatus.NO_PAY.getCode());  //待付款
        // 写到数据库中
        orderMapper.insert(order);
        log.info("订单生成成功");

        // 清空Redis中的购物车，使用异步操作
        rabbitTemplate.convertAndSend("clear.cart.queue", cartVo);

        //7、将订单存入队列（40分钟）中，定时判断用户是否已经完成订单支付
        rabbitTemplate.convertAndSend("order.exchange","order.key.normal", order);

        return Number;
    }
}




